Skip to content

Conversation

@fatguru
Copy link

@fatguru fatguru commented Dec 11, 2025

Hi Team,

This PR addresses False Negatives caused by middleware.ts redirects on the root path (/).

The Problem:
Currently, the scanner defaults to probing ["/"]. In many Next.js deployments, the root path redirects (e.g., 307 to /login). This redirection often strips the POST body before the RSC parser processes it, causing the scanner to miss vulnerable targets.

The Fix:
I updated the default logic to probe both / AND /{random_string}.
Hitting a non-existent path triggers the Next.js Global Not Found handler (which is an RSC). This forces the server to parse the payload regardless of authentication middleware or root redirects.

Issue associated: Fixes #27

Cheers!

@infosec-au
Copy link
Contributor

Hi @fatguru - we should be sending the POST to both the index, and any on-site redirected path, are you seeing behaviour that doesn't show this?

# FIX: Use the redirection from the POST response directly.
Calling resolve_redirects() sends a HEAD request, which often receives  a 200 OK on Next.js/RSC apps instead of the 307/303 triggered by POST.
@fatguru
Copy link
Author

fatguru commented Dec 19, 2025

Hi @infosec-au / Shubs,

Thanks for the follow up. I have updated the branch with the fix. I also deployed a live reproduction case on Vercel to demonstrate exactly why relying on HEAD requests (resolve_redirects) causes false negatives on Next.js environments using Middleware.

The Logic Flaw: Next.js Middleware often behaves differently based on the HTTP Verb.

  • HEAD /: Returns 200 OK (Static shell/Home page).
  • POST /: Returns 307 Temporary Redirect (e.g., forcing auth/login for Actions).

Because the current scanner uses HEAD to check for redirects, it receives a 200, assumes there is no redirection, and fails to follow the attack path.

Live Proof of Concept:

Target URL: https://nextjs-middleware-a5780xxfd-fatgurus-projects.vercel.app/

Middleware Logic: Source Code (Redirects POST on root to /pwned).

Verification Logs:

I ran both versions of the scanner against this PoC.

  1. Original Logic (Broken): It sees the 307 from the POST, but because the internal check uses HEAD (which returns 200), it assumes the path is static and stops.
$ python3 scanner_old.py -u https://nextjs-middleware-a5780xxfd-fatgurus-projects.vercel.app

brought to you by assetnote

[*] Loaded 1 host(s) to scan
[*] Using 10 thread(s)
[*] Timeout: 10s
[*] Using RCE PoC check
[!] SSL verification disabled

[NOT VULNERABLE] https://nextjs-middleware-a5780xxfd-fatgurus-projects.vercel.app - Status: 307
  Response snippet:
    HTTP/1.1 307 Temporary Redirect
    Cache-Control: public, max-age=0, must-revalidate
    Content-Type: text/plain
    Date: Fri, 19 Dec 2025 16:23:44 GMT
    Location: /pwned
    Server: Vercel
    Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
    X-Robots-Tag: noindex
    X-Vercel-Id: iad1::h8m6c-1766161424761-2defd3775d2e
    Transfer-Encoding: chunked

============================================================
SCAN SUMMARY
============================================================
  Total hosts scanned: 1
  Vulnerable: 0
  Not vulnerable: 1
  Errors: 0
============================================================

Result: Scanner stops here. Never probes /pwned.

  1. Patched Logic (Working): This PR updates the logic to respect the Location header returned by the initial POST probe, correctly following the flow defined by the middleware.
$ python3 scanner_new.py -u https://nextjs-middleware-a5780xxfd-fatgurus-projects.vercel.app

brought to you by assetnote

[*] Loaded 1 host(s) to scan
[*] Using 10 thread(s)
[*] Timeout: 10s
[*] Using RCE PoC check
[!] SSL verification disabled


[DEBUG] FIX WORKING! Following redirect to: https://nextjs-middleware-a5780xxfd-fatgurus-projects.vercel.app/pwned
[NOT VULNERABLE] https://nextjs-middleware-a5780xxfd-fatgurus-projects.vercel.app - Status: 405
  -> Redirected to: https://nextjs-middleware-a5780xxfd-fatgurus-projects.vercel.app/pwned
  Response snippet:
    HTTP/1.1 405 Method Not Allowed
    Cache-Control: public, max-age=0, must-revalidate
    Content-Disposition: inline; filename="404"
    Content-Type: text/html; charset=utf-8
    Date: Fri, 19 Dec 2025 16:28:14 GMT
    Server: Vercel
    Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
    X-Matched-Path: /404
    X-Robots-Tag: noindex
    X-Vercel-Cache: BYPASS

============================================================
SCAN SUMMARY
============================================================
  Total hosts scanned: 1
  Vulnerable: 0
  Not vulnerable: 1
  Errors: 0
============================================================

Result: Scanner successfully follows redirect and probes /pwned.

(Note: Status 405 is expected here as the PoC endpoint doesn't accept POST, but it confirms the scanner reached the target destination).

The code is updated and ready for review.

Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[False Negative] Scanner fails on targets with Root Redirects (Next.js Middleware)

2 participants